--------------------------- -- task manager extender -- by Alundaio -- IMPORTANT 'task' is global namespace! use 'tsk' or something -- Modified by: DoctorX -- Last revised: November 12, 2016 -- Modified by Tronex for fixing bugs with drx quests -- Modified by tdef with adding ability to define custom names with no need for numric order for patterns --------------------------- --actor_tagged_squad_by_id = {} bounties_by_id = {} available_tasks = {} ongoing_tasks = {} finished_tasks = {} hostages_by_id = {} ----------------------------------------------------------------------------- -- FACTION QUESTLINES HONCHO ----------------------------------------------------------------------------- drx_sl_main_honcho_table = { ["stalker"] = "esc_m_trader", ["dolg"] = "bar_dolg_general_petrenko_stalker", ["freedom"] = "mil_smart_terrain_7_7_freedom_leader_stalker", ["csky"] = "mar_smart_terrain_base_stalker_leader_marsh", ["ecolog"] = "yan_stalker_sakharov", ["killer"] = "cit_killers_merc_trader_stalker", ["army"] = "agr_smart_terrain_1_6_near_2_military_colonel_kovalski", ["bandit"] = "zat_b7_bandit_boss_sultan", ["monolith"] = "pri_monolith_monolith_trader_stalker", ["renegade"] = "zat_b7_bandit_boss_sultan", ["greh"] = "red_greh_trader", ["isg"] = "cit_killers_merc_trader_stalker", } drx_sl_honchos_table = { -- Loner honchos: {"esc_m_trader", "stalker"}, -- Cordon - Sidorovich (Loner Trader) {"esc_smart_terrain_5_7_loner_mechanic_stalker", "stalker"}, -- Cordon - Xenotech (Loner Mechanic) {"zat_a2_stalker_barmen", "stalker"}, -- Zaton - Beard (Loner Trader) {"zat_b18_noah", "stalker"}, -- Zaton - Noah (Loner Honcho) -- Duty honchos: {"bar_dolg_general_petrenko_stalker", "dolg"}, -- Rostok - Petrenko (Duty Trader) {"bar_visitors_stalker_mechanic", "dolg"}, -- Rostok - Mangun (Duty Mechanic) -- Freedom honchos: {"mil_smart_terrain_7_7_freedom_leader_stalker", "freedom"}, -- Military Warehouses - Lukash (Freedom Honcho) {"jup_a6_freedom_leader", "freedom", "stalker"}, -- Jupiter - Loki (Freedom Honcho) -- Clear Sky honchos: {"mar_smart_terrain_base_stalker_leader_marsh", "csky"}, -- Great Swamp - Cold (Clear Sky Honcho) {"mar_base_stalker_barmen", "csky"}, -- Great Swamp - Librarian (Clear Sky Trader) -- Ecologist honchos: {"yan_stalker_sakharov", "ecolog"}, -- Yantar - Sakharov (Ecologist Trader) {"jup_b6_scientist_tech", "ecolog", "stalker"}, -- Jupiter - Tukarev (Ecologist Mechanic) -- Mercenary honchos: {"cit_killers_merc_trader_stalker", "killer"}, -- Dead City - Dushman (Mercenary Trader) {"cit_killers_merc_mechanic_stalker", "killer"}, -- Dead City - Hog (Mercenary Mechanic) {"cit_killers_merc_mechanic_stalker", "killer"}, -- Zaton - Vector (Mercenary Trader) {"merc_pri_grifon_mlr", "killer"}, -- Outskirts - Griffith (Mercenary Operator) -- Military honchos: {"agr_smart_terrain_1_6_near_2_military_colonel_kovalski", "army"}, -- Agoroprom - Kuznetsov (Military Honcho) {"agr_smart_terrain_1_6_army_mechanic_stalker", "army"}, -- Agoroprom - Kirilov (Military Mechanic) -- Bandit honchos: {"zat_b7_bandit_boss_sultan", "bandit"}, -- Dark Valley - Sultan (Bandit Honcho) {"val_smart_terrain_7_4_bandit_trader_stalker", "bandit"}, -- Dark Valley - Olivius (Bandit Trader) {"jup_cont_trader_bandit", "bandit"}, -- Jupiter - Klenov (Bandit Trader) -- Monolith honchos: {"pri_monolith_monolith_trader_stalker", "monolith"}, -- Pripyat - Rabbit (Monolith Trader) {"pri_monolith_monolith_mechanic_stalker", "monolith"}, -- Pripyat - Cleric (Monolith Mechanic) {"trader_monolith_kbo", "monolith"}, -- Outskirts - Olivar (Monolith Trader) -- Sin honchos: {"red_greh_trader", "greh"}, -- Red Forest - Stribog (Sin Trader) {"red_greh_tech", "greh"}, -- Red Forest - Dazhbog (Sin Mechanic) } ----------------------------------------------------------------------------- -- PRIVATE ----------------------------------------------------------------------------- local function npc_on_death_callback(npc,who) local id = npc:id() for task_id,npc_id in pairs(bounties_by_id) do if (npc_id == id) then if (db.storage[id] and db.storage[id].tagged_by_actor == true) or (who and (who:id() == 0 or who:has_info("npcx_is_companion"))) then local tm = task_manager.get_task_manager() local tsk = tm.task_info[task_id] if (tsk and tsk.stage == 0) then tsk.stage = 1 end else local tm = task_manager.get_task_manager() local tsk = tm.task_info[task_id] if (tsk and tsk.stage == 0) then --tsk.stage = 3 tsk.stage = 1 -- complete task anyway instead of failing end end return end end end local function npc_on_hit_callback(npc,amount,local_direction,who,bone_index) local id = who and who:id() if not (id) then return end if (id == AC_ID or IsStalker(who) and who:has_info("npcx_is_companion")) then local npc_id = npc:id() if (db.storage[npc_id]) then db.storage[npc_id].tagged_by_actor = true end end end local function squad_on_npc_death(squad,se_npc,killer) -- unregister ID as task giver or pass id onto squad leader if is_sim task local task_info = task_manager.get_task_manager().task_info for k,v in pairs(task_info) do if (v.task_giver_id and v.task_giver_id == se_npc.id) then if (squad:npc_count() > 0 and string.find(k,"simulation_task_")) then task_info[k].task_giver_id = squad:commander_id() else task_info[k].task_giver_id = nil end return end end end local function save_state(m_data) m_data.bounties_by_id = bounties_by_id m_data.hostages_by_id = hostages_by_id end local function load_state(m_data) if (m_data.bounties_by_id) then bounties_by_id = m_data.bounties_by_id m_data.bounties_by_id = nil end if (m_data.hostages_by_id) then hostages_by_id = m_data.hostages_by_id m_data.hostages_by_id = nil end generate_cache() end local function on_before_level_changing() local actor = db.actor local tm = task_manager.get_task_manager() local task_info = tm.task_info task_manager.task_ini:section_for_each(function(task_id) if task_info[task_id] == nil then local var = load_var(actor,task_id) local var_fetch = load_var(actor,task_id .. "_fetch") if var then save_var(actor, task_id, nil) printdbg("~ axr_task_manager | cleaned unused task var [%s]", task_id) elseif var_fetch then save_var(actor, task_id .. "_fetch", nil) save_var(actor, task_id .. "_count", nil) printdbg("~ axr_task_manager | cleaned unused fetch task var [%s]", task_id) end end end) end CFG_CACHE = {} function generate_cache() function x(section) CFG_CACHE[section] = {} CFG_CACHE[section].stage_complete = task_manager.task_ini:r_float_ex( section, "stage_complete" ) CFG_CACHE[section].sim_communities = task_manager.task_ini:r_string_ex( section, "sim_communities" ) CFG_CACHE[section].job_descr = task_manager.task_ini:r_string_ex( section, "job_descr" ) CFG_CACHE[section].fetch_descr = task_manager.task_ini:r_string_ex( section, "fetch_descr" ) CFG_CACHE[section].fetch_func = task_manager.task_ini:r_string_ex( section, "fetch_func" ) CFG_CACHE[section].task_complete_descr = task_manager.task_ini:r_string_ex( section, "task_complete_descr" ) CFG_CACHE[section].can_cancel = task_manager.task_ini:r_string_ex( section, "can_cancel" ) CFG_CACHE[section].on_job_descr = task_manager.task_ini:r_string_ex( section, "on_job_descr" ) end task_manager.task_ini:section_for_each(x) -- utils_data.print_table(CFG_CACHE,strformat('parsed_task_data', section)) end -- Modified by DoctorX - List of skipped tasks local skipped_tasks = {} ----------------------------------------------------------------------------- -- ON GAME START ----------------------------------------------------------------------------- function on_game_start() RegisterScriptCallback("npc_on_death_callback",npc_on_death_callback) RegisterScriptCallback("npc_on_hit_callback",npc_on_hit_callback) RegisterScriptCallback("monster_on_hit_callback",npc_on_hit_callback) RegisterScriptCallback("squad_on_npc_death",squad_on_npc_death) RegisterScriptCallback("save_state",save_state) RegisterScriptCallback("load_state",load_state) RegisterScriptCallback("on_before_level_changing",on_before_level_changing) end ------------------------------------------------------------------------------ -- PUBLIC ------------------------------------------------------------------------------ -- Created by DoctorX - Returns the task ID of a random available storyline task for the current honcho -- Generate valid random task id for current honcho: function drx_sl_generate_random_sl_task( npc, skip, is_sim ) local tm = task_manager.get_task_manager( ) local task_info = tm.task_info -- Get task section: local sec local st = db.storage[npc:id( )] if ( st and st.ini and st.section_logic ) then sec = st.ini:r_string_ex( st.section_logic, "task_section" ) if ( sec ) then sec = ("drx_sl_" .. sec .. "_task_") end end if not ( sec ) then sec = npc:section( ) ~= "m_trader" and ("drx_sl_" .. npc:section( ) .. "_task_") or ("drx_sl_" .. npc:name( ) .. "_task_") end -- Build list of valid tasks: local honcho_task_list = {} local size_t = 0 for task_id in pairs(CFG_CACHE) do if starts_with(task_id, sec) then if ( skipped_tasks[task_id] ~= true and task_info[task_id] == nil and xr_conditions.has_completed_task_prerequisites( nil, nil, {task_id} ) ) then if ( skip ) then skipped_tasks[task_id] = true return else size_t = size_t + 1 honcho_task_list[size_t] = task_id end end end end -- old code --[[ local task_id = (sec .. "1") local count = 1 while ( task_manager.task_ini:section_exist( task_id ) ) do if ( skipped_tasks[task_id] ~= true and task_info[task_id] == nil and xr_conditions.has_completed_task_prerequisites( nil, nil, {task_id} ) ) then if ( skip ) then skipped_tasks[task_id] = true return else size_t = size_t + 1 honcho_task_list[size_t] = task_id end end count = (count + 1) task_id = (sec .. tostring( count )) end -]] -- Pick random task from list of valid tasks: if ( #honcho_task_list > 0 ) then math.randomseed( device( ):time_global( ) ) return honcho_task_list[math.random( #honcho_task_list )] else return ("drx_sl_" .. load_var( db.actor, "drx_sl_current_honcho", "" ) .. "_default_task") end end -- Created by DoctorX - Returns the task ID of a random available change factions task for the current npc -- Generate valid change factions task id for current npc: function drx_sl_generate_change_factions_task( npc, skip, is_sim ) local tm = task_manager.get_task_manager( ) local task_info = tm.task_info -- Get task section: local sec local st = db.storage[npc:id( )] if ( st and st.ini and st.section_logic ) then sec = st.ini:r_string_ex( st.section_logic, "task_section" ) if ( sec ) then sec = ("drx_sl_" .. sec .. "_cf_task_") end end if not ( sec ) then sec = npc:section( ) ~= "m_trader" and ("drx_sl_" .. npc:section( ) .. "_cf_task_") or ("drx_sl_" .. npc:name( ) .. "_cf_task_") end -- Build list of valid tasks: local task_list = {} local size_t = 0 for task_id in pairs(CFG_CACHE) do if starts_with(task_id, sec) then if ( skipped_tasks[task_id] ~= true and task_info[task_id] == nil and xr_conditions.has_completed_task_prerequisites( nil, nil, {task_id} ) ) then if ( skip ) then skipped_tasks[task_id] = true return else size_t = size_t + 1 task_list[size_t] = task_id end end end end -- old code --[[ local task_id = (sec .. "1") local count = 1 while ( task_manager.task_ini:section_exist( task_id ) ) do if ( skipped_tasks[task_id] ~= true and task_info[task_id] == nil and xr_conditions.has_completed_task_prerequisites( nil, nil, {task_id} ) ) then if ( skip ) then skipped_tasks[task_id] = true return else size_t = size_t + 1 task_list[size_t] = task_id end end count = (count + 1) task_id = (sec .. tostring( count )) end --]] -- Pick random task from list of valid tasks: if ( #task_list > 0 ) then math.randomseed( device( ):time_global( ) ) return task_list[math.random( #task_list )] else return "" end end -- Modified by DoctorX - Returns the task ID of a random available dynamic task for the current NPC -- Generate valid random task id for current NPC: function get_first_available_task( npc, skip, is_sim ) local tm = task_manager.get_task_manager( ) local task_info = tm.task_info -- Get current stored task for current npc: local npc_stored_task = load_var( db.actor, ("drx_sl_npc_stored_task_" .. npc:id( )), nil ) local time_last_checked = load_ctime( db.actor, ("drx_sl_npc_stored_task_time_" .. npc:id( )) ) -- Check stored task has not timed out (<3hrs): if ( time_last_checked and game.get_game_time( ):diffSec( time_last_checked ) < 5400 ) then -- Check if stored task is still valid: if ( not npc_stored_task ) then return elseif ( task_info[npc_stored_task] == nil and xr_conditions.has_completed_task_prerequisites( nil, nil, {npc_stored_task} ) ) then return npc_stored_task else return end end -- Decide if current npc should have task to give (75% chance): math.randomseed( device( ):time_global( ) ) if ( math.random( 100 ) > 75 ) then save_var( db.actor, ("drx_sl_npc_stored_task_" .. npc:id( )), nil ) save_ctime( db.actor, ("drx_sl_npc_stored_task_time_" .. npc:id( )), game.get_game_time( ) ) return end -- If no valid stored task then generate new task: local sec local st = db.storage[npc:id( )] if ( st and st.ini and st.section_logic ) then sec = st.ini:r_string_ex( st.section_logic, "task_section" ) if ( sec ) then sec = (sec .. "_task_") end end if not ( sec ) then sec = (is_sim and "simulation_task_" or npc:section( ) ~= "m_trader" and (npc:section( ) .. "_task_") or (npc:name( ) .. "_task_")) end -- Build list of valid tasks: local npc_task_list = {} local size_t = 0 for task_id in pairs(CFG_CACHE) do if starts_with(task_id, sec) then if ( skipped_tasks[task_id] ~= true and task_info[task_id] == nil and xr_conditions.has_completed_task_prerequisites( nil, nil, {task_id} ) ) then if ( skip ) then skipped_tasks[task_id] = true return else if ( is_sim ) then local p = parse_list( task_manager.task_ini, task_id, "sim_communities", true ) if ( p[character_community( npc )] == true ) then size_t = size_t + 1 npc_task_list[size_t] = task_id end else size_t = size_t + 1 npc_task_list[size_t] = task_id end end end end end -- old code --[[ local task_id = (sec .. "1") local count = 1 while ( task_manager.task_ini:section_exist( task_id ) ) do if ( skipped_tasks[task_id] ~= true and task_info[task_id] == nil and xr_conditions.has_completed_task_prerequisites( nil, nil, {task_id} ) ) then if ( skip ) then skipped_tasks[task_id] = true return else if ( is_sim ) then local p = parse_list( task_manager.task_ini, task_id, "sim_communities", true ) if ( p[character_community( npc )] == true ) then size_t = size_t + 1 npc_task_list[size_t] = task_id end else size_t = size_t + 1 npc_task_list[size_t] = task_id end end end count = (count + 1) task_id = (sec .. tostring( count )) end -]] -- Pick random task from list of valid tasks: local new_task if ( #npc_task_list > 0 ) then math.randomseed( device( ):time_global( ) ) new_task = npc_task_list[math.random( #npc_task_list )] end -- Store current available task for current npc: save_var( db.actor, ("drx_sl_npc_stored_task_" .. npc:id( )), new_task ) save_ctime( db.actor, ("drx_sl_npc_stored_task_time_" .. npc:id( )), game.get_game_time( ) ) return new_task end -- Modified by DoctorX - Returns the task ID of a random available mechanic task for the current NPC -- Generate valid mechanic task id for current NPC: function drx_sl_get_mechanic_task( npc, skip, is_sim ) local tm = task_manager.get_task_manager( ) local task_info = tm.task_info -- Get section: local sec local st = db.storage[npc:id( )] if ( st and st.ini and st.section_logic ) then sec = st.ini:r_string_ex( st.section_logic, "task_section" ) if ( sec ) then sec = (sec .. "_task_") end end if not ( sec ) then sec = (is_sim and "simulation_task_" or npc:section( ) ~= "m_trader" and (npc:section( ) .. "_task_") or (npc:name( ) .. "_task_")) end -- Build list of valid tasks: local npc_task_list = {} local size_t = 0 for task_id in pairs(CFG_CACHE) do if starts_with(task_id, sec) then if ( skipped_tasks[task_id] ~= true and task_info[task_id] == nil and xr_conditions.has_completed_task_prerequisites( nil, nil, {task_id} ) ) then if ( skip ) then skipped_tasks[task_id] = true return else if ( is_sim ) then local p = parse_list( task_manager.task_ini, task_id, "sim_communities", true ) if ( p[character_community( npc )] == true ) then size_t = size_t + 1 npc_task_list[size_t] = task_id end else size_t = size_t + 1 npc_task_list[size_t] = task_id end end end end end -- old code --[[ local task_id = (sec .. "1") local count = 1 while ( task_manager.task_ini:section_exist( task_id ) ) do if ( skipped_tasks[task_id] ~= true and task_info[task_id] == nil and xr_conditions.has_completed_task_prerequisites( nil, nil, {task_id} ) ) then if ( skip ) then skipped_tasks[task_id] = true return else if ( is_sim ) then local p = parse_list( task_manager.task_ini, task_id, "sim_communities", true ) if ( p[character_community( npc )] == true ) then size_t = size_t + 1 npc_task_list[size_t] = task_id end else size_t = size_t + 1 npc_task_list[size_t] = task_id end end end count = (count + 1) task_id = (sec .. tostring( count )) end --]] -- Pick random task from list of valid tasks: local new_task if ( #npc_task_list > 0 ) then math.randomseed( device( ):time_global( ) ) new_task = npc_task_list[math.random( #npc_task_list )] end -- Return task ID: return new_task end -- Created by DoctorX - Determines whether or not the player has a storyline task that is finished -- Determine if actor has completed current storyline task: function drx_sl_get_finished_task( npc, is_sim ) local tm = task_manager.get_task_manager( ) local task_info = tm.task_info local sec local st = db.storage[npc:id( )] -- Check if player is on end game task: local endgame_task = load_var( db.actor, "drx_sl_endgame_task", "" ) if ( endgame_task ~= "" ) then if ( db.actor:get_task( endgame_task, true ) ~= nil and task_info[endgame_task] and task_info[endgame_task].stage ~= nil and task_info[endgame_task].stage == (CFG_CACHE[endgame_task].stage_complete or 254) ) then if ( task_info[endgame_task].status ~= "fail" and task_info[endgame_task].status ~= "completed" ) then return endgame_task end end end if ( st and st.ini and st.section_logic ) then sec = st.ini:r_string_ex( st.section_logic, "task_section" ) if ( sec ) then sec = (sec .. "_task_") end end if not ( sec ) then sec = npc:section() ~= "m_trader" and ("drx_sl_" .. npc:section( ) .. "_task_") or ("drx_sl_" .. npc:name( ) .. "_task_") end for task_id in pairs(CFG_CACHE) do if starts_with(task_id, sec) then if ( db.actor:get_task( task_id, true ) ~= nil and task_info[task_id] and task_info[task_id].stage ~= nil and task_info[task_id].stage == (CFG_CACHE[task_id].stage_complete or 254) ) then if ( task_info[task_id].status ~= "fail" and task_info[task_id].status ~= "completed" ) then return task_id end end end end -- old code --[[ local task_id = (sec .. "1") local count = 1 while ( task_manager.task_ini:section_exist( task_id ) ) do if ( db.actor:get_task( task_id, true ) ~= nil and task_info[task_id] and task_info[task_id].stage ~= nil and task_info[task_id].stage == (task_manager.task_ini:r_float_ex( task_id, "stage_complete" ) or 254) ) then if ( task_info[task_id].status ~= "fail" and task_info[task_id].status ~= "completed" ) then return task_id end end count = (count + 1) task_id = (sec .. tostring( count )) end --]] end -- Created by DoctorX - Determines whether or not the player has a change factions task that is finished -- Determine if actor has completed change factions task: function drx_sl_get_finished_cf_task( npc, is_sim ) local tm = task_manager.get_task_manager( ) local task_info = tm.task_info local sec local st = db.storage[npc:id( )] if ( st and st.ini and st.section_logic ) then sec = st.ini:r_string_ex( st.section_logic, "task_section" ) if ( sec ) then sec = (sec .. "_cf_task_") end end if not ( sec ) then sec = npc:section() ~= "m_trader" and ("drx_sl_" .. npc:section( ) .. "_cf_task_") or ("drx_sl_" .. npc:name( ) .. "_cf_task_") end for task_id in pairs(CFG_CACHE) do if starts_with(task_id, sec) then if ( db.actor:get_task( task_id, true ) ~= nil and task_info[task_id] and task_info[task_id].stage ~= nil and task_info[task_id].stage == (CFG_CACHE[task_id].stage_complete or 254) ) then if ( task_info[task_id].status ~= "fail" and task_info[task_id].status ~= "completed" ) then return task_id end end end end -- old code --[[ local task_id = (sec .. "1") local count = 1 while ( task_manager.task_ini:section_exist( task_id ) ) do if ( db.actor:get_task( task_id, true ) ~= nil and task_info[task_id] and task_info[task_id].stage ~= nil and task_info[task_id].stage == (task_manager.task_ini:r_float_ex( task_id, "stage_complete" ) or 254) ) then if ( task_info[task_id].status ~= "fail" and task_info[task_id].status ~= "completed" ) then return task_id end end count = (count + 1) task_id = (sec .. tostring( count )) end --]] end -- Created by DoctorX - Sets the current storyline task to complete -- Set current storyline task to complete: function drx_sl_set_finished_task_complete( npc, is_sim ) local task_id = drx_sl_get_finished_task( npc, is_sim ) if not ( task_id ) then printf( "WARNING: axr_task_manager.drx_sl_set_finished_task_complete: no task %s", task_id ) return end task_manager.get_task_manager():set_task_completed(task_id) end -- Created by DoctorX - Sets the current change faction task to complete -- Set current change faction task to complete: function drx_sl_set_finished_cf_task_complete( npc, is_sim ) local task_id = drx_sl_get_finished_cf_task( npc, is_sim ) if not ( task_id ) then printf( "WARNING: axr_task_manager.drx_sl_set_finished_cf_task_complete: no task %s", task_id ) return end task_manager.get_task_manager( ):set_task_completed( task_id ) end -- Modified by DoctorX - Gets the first finished task id -- Get first finished task: function get_first_finished_task( npc, is_sim ) local tm = task_manager.get_task_manager( ) local task_info = tm.task_info local sec local st = db.storage[npc:id( )] if ( st and st.ini and st.section_logic ) then sec = st.ini:r_string_ex( st.section_logic, "task_section" ) if ( sec ) then sec = (sec .. "_task_") end end if not ( sec ) then sec = is_sim and "simulation_task_" or npc:section( ) ~= "m_trader" and (npc:section( ) .. "_task_") or (npc:name( ) .. "_task_") end for task_id in pairs(CFG_CACHE) do if starts_with(task_id, sec) then if ( db.actor:get_task( task_id, true ) ~= nil and task_info[task_id] and task_info[task_id].stage ~= nil and task_info[task_id].stage == (CFG_CACHE[task_id].stage_complete or 254) ) then if ( task_info[task_id].status ~= "fail" and task_info[task_id].status ~= "completed" ) then if ( is_sim and task_info[task_id].task_giver_id ) then if ( npc:id() == task_info[task_id].task_giver_id ) then return task_id end local se_obj = alife( ):object( npc:id( ) ) if ( se_obj and se_obj.group_id ~= 65535 and se_obj.group_id == task_info[task_id].task_giver_id ) then return task_id end else return task_id end end end end end -- old code --[[ local task_id = (sec .. "1") local count = 1 while ( task_manager.task_ini:section_exist( task_id ) ) do if ( db.actor:get_task( task_id, true ) ~= nil and task_info[task_id] and task_info[task_id].stage ~= nil and task_info[task_id].stage == (task_manager.task_ini:r_float_ex( task_id, "stage_complete" ) or 254) ) then if ( task_info[task_id].status ~= "fail" and task_info[task_id].status ~= "completed" ) then if ( is_sim and task_info[task_id].task_giver_id ) then if ( npc:id() == task_info[task_id].task_giver_id ) then return task_id end local se_obj = alife( ):object( npc:id( ) ) if ( se_obj and se_obj.group_id ~= 65535 and se_obj.group_id == task_info[task_id].task_giver_id ) then return task_id end else return task_id end end end count = (count + 1) task_id = (sec .. tostring( count )) end --]] end -- Modified by DoctorX - Sets the current task to complete -- Set current task to complete: function set_finished_task_complete( npc, is_sim ) local task_id = get_first_finished_task( npc, is_sim ) if not ( task_id ) then printf( "WARNING: axr_task_manager.set_finished_task_complete: no task %s", task_id ) return end task_manager.get_task_manager( ):set_task_completed( task_id ) end -- Modified by DoctorX - Gives the player the current task -- Give the player the current task: function npc_give_first_available_ordered_task( npc, is_sim ) local new_task = get_first_available_task( npc, nil, is_sim ) if ( not new_task ) then return end local se_obj = npc and alife( ):object( npc:id( ) ) local giver_id = se_obj and (se_obj.group_id ~= 65535 and se_obj.group_id or se_obj.id) task_manager.get_task_manager( ):give_task( new_task, giver_id ) return new_task end -- Modified by DoctorX - Gets the job description for a task -- Get the job description of the task: function get_task_job_description( task_id ) return CFG_CACHE[task_id] and CFG_CACHE[task_id].job_descr and game.translate_string(CFG_CACHE[task_id].job_descr) end -- Modified by DoctorX - Gets the description for a fetch task -- Get the description of the fetch task: function get_fetch_task_description( task_id ) return CFG_CACHE[task_id] and CFG_CACHE[task_id].fetch_descr and game.translate_string(CFG_CACHE[task_id].fetch_descr) end -- Modified by DoctorX - Gets the text for a completed task -- Get the text for a completed task: function get_task_complete_text( task_id ) return CFG_CACHE[task_id] and CFG_CACHE[task_id].task_complete_descr and game.translate_string(CFG_CACHE[task_id].task_complete_descr) end -- Modified by DoctorX - Clears skipped task list -- Clear skipped task list: function clear_skipped_tasks( ) empty_table( skipped_tasks ) end -- automated ordered tasks -- tasks must be named
_task_ -- m_trader (ie. Sidorovich) use npc:name() instead function generate_available_tasks(npc,is_sim) local id = npc:id() if not (available_tasks[id]) then available_tasks[id] = {} else empty_table(available_tasks[id]) end local tm = task_manager.get_task_manager() local task_info = tm.task_info local sec local st = db.storage[npc:id()] -- Randomly not offer any quests at all for sim npcs if (is_sim and st.dyn_quest_rand == nil) then if ( (math.random(1,100)/100) < 0.3) then st.dyn_quest_rand = "nil" return end end if (st and st.ini and st.section_logic) then sec = st.ini:r_string_ex(st.section_logic,"task_section") if (sec) then sec = sec .. "_task_" end end if not (sec) then sec = is_sim and "simulation_task_" or npc:section() ~= "m_trader" and npc:section().."_task_" or npc:name().."_task_" end local t local size_t = 0 for task_id in pairs(CFG_CACHE) do if starts_with(task_id, sec) then if (task_info[task_id] == nil and xr_conditions.has_completed_task_prerequisites(nil,nil,{task_id})) then if (is_sim) then local p = parse_list(task_manager.task_ini,task_id,"sim_communities",true) if (p[character_community(npc)] == true) then if not (t) then t = {} end if (st.dyn_quest_rand == task_id) then size_t = size_t + 1 available_tasks[id][size_t] = task_id return elseif (st.dyn_quest_rand == nil) then t[#t+1] = task_id end end else size_t = size_t + 1 available_tasks[id][size_t] = task_id end end end end -- old code --[[ local task_id = sec.."1" local count = 1 while (task_manager.task_ini:section_exist(task_id)) do --printf("task_id=%s skipped=%s",task_id,skipped_tasks[task_id]) if (task_info[task_id] == nil and xr_conditions.has_completed_task_prerequisites(nil,nil,{task_id})) then if (is_sim) then local p = parse_list(task_manager.task_ini,task_id,"sim_communities",true) if (p[character_community(npc)] == true) then if not (t) then t = {} end if (st.dyn_quest_rand == task_id) then size_t = size_t + 1 available_tasks[id][size_t] = task_id return elseif (st.dyn_quest_rand == nil) then t[#t+1] = task_id end end else size_t = size_t + 1 available_tasks[id][size_t] = task_id end end count = count + 1 task_id = sec..tostring(count) end --]] -- randomize available tasks from sim npcs and only offer 1 job; remembing this job until NPC go offline if (t and #t > 0) then st.dyn_quest_rand = t[math.random(#t)] size_t = size_t + 1 available_tasks[id][size_t] = st.dyn_quest_rand end end function generate_ongoing_tasks(npc,is_sim) local id = npc:id() if not (ongoing_tasks[id]) then ongoing_tasks[id] = {} else empty_table(ongoing_tasks[id]) end local tm = task_manager.get_task_manager() local task_info = tm.task_info local sec local st = db.storage[npc:id()] if (st and st.ini and st.section_logic) then sec = st.ini:r_string_ex(st.section_logic,"task_section") if (sec) then sec = sec .. "_task_" end end if not (sec) then sec = is_sim and "simulation_task_" or npc:section() ~= "m_trader" and npc:section().."_task_" or npc:name().."_task_" end local size_t = 0 for task_id in pairs(CFG_CACHE) do if starts_with(task_id, sec) then local task_can_be_cancelled = CFG_CACHE[task_id].can_cancel if (task_can_be_cancelled == nil or task_can_be_cancelled == true) then if (db.actor:get_task(task_id,true) and task_info[task_id] and task_info[task_id].stage and task_info[task_id].stage < (CFG_CACHE[task_id].stage_complete or 255)) then if (task_info[task_id].status ~= "fail" and task_info[task_id].status ~= "completed") then if is_sim or (_G.WARFARE and warfare.is_warfare_trader(npc)) then -- xQd, make each warfare trader have their own separate tasks like sim npcs if (task_info[task_id].task_giver_id) then if (npc:id() == task_info[task_id].task_giver_id) then size_t = size_t + 1 ongoing_tasks[id][size_t] = task_id end end else size_t = size_t + 1 ongoing_tasks[id][size_t] = task_id end end end end end end -- old code --[[ local task_id = sec.."1" local count = 1 while (task_manager.task_ini:section_exist(task_id)) do local task_can_be_cancelled = task_manager.task_ini:r_bool_ex(task_id,"can_cancel",true) if (task_can_be_cancelled == nil or task_can_be_cancelled == true) then if (db.actor:get_task(task_id,true) and task_info[task_id] and task_info[task_id].stage and task_info[task_id].stage < (task_manager.task_ini:r_float_ex(task_id,"stage_complete") or 255)) then if (task_info[task_id].status ~= "fail" and task_info[task_id].status ~= "completed") then if is_sim or (_G.WARFARE and warfare.is_warfare_trader(npc)) then xQd, make each warfare trader have their own separate tasks like sim npcs if (task_info[task_id].task_giver_id) then if (npc:id() == task_info[task_id].task_giver_id) then size_t = size_t + 1 ongoing_tasks[id][size_t] = task_id end end else size_t = size_t + 1 ongoing_tasks[id][size_t] = task_id end end end end count = count + 1 task_id = sec..tostring(count) end --]] end function generate_finished_tasks(npc,is_sim) local id = npc:id() if not (finished_tasks[id]) then finished_tasks[id] = {} else empty_table(finished_tasks[id]) end local tm = task_manager.get_task_manager() local task_info = tm.task_info local sec local st = db.storage[npc:id()] if (st and st.ini and st.section_logic) then sec = st.ini:r_string_ex(st.section_logic,"task_section") if (sec) then sec = sec .. "_task_" end --printf("sec = %s") end if not (sec) then sec = is_sim and "simulation_task_" or npc:section() ~= "m_trader" and npc:section().."_task_" or npc:name().."_task_" end local size_t = 0 for task_id in pairs(CFG_CACHE) do if starts_with(task_id, sec) then if (db.actor:get_task(task_id, true) ~= nil and task_info[task_id] and task_info[task_id].stage ~= nil and task_info[task_id].stage == (CFG_CACHE[task_id].stage_complete or 255)) then if (task_info[task_id].status ~= "fail" and task_info[task_id].status ~= "completed") then if (is_sim or warfare.is_warfare_trader(npc)) then -- xQd, make each warfare trader have their own separate tasks like sim npcs if (task_info[task_id].task_giver_id) then if (npc:id() == task_info[task_id].task_giver_id) then size_t = size_t + 1 finished_tasks[id][size_t] = task_id end end else size_t = size_t + 1 finished_tasks[id][size_t] = task_id end end end end end -- old code --[[ local task_id = sec.."1" local count = 1 while (task_manager.task_ini:section_exist(task_id)) do if (db.actor:get_task(task_id, true) ~= nil and task_info[task_id] and task_info[task_id].stage ~= nil and task_info[task_id].stage == (task_manager.task_ini:r_float_ex(task_id,"stage_complete") or 255)) then if (task_info[task_id].status ~= "fail" and task_info[task_id].status ~= "completed") then if (is_sim or warfare.is_warfare_trader(npc)) then xQd, make each warfare trader have their own separate tasks like sim npcs if (task_info[task_id].task_giver_id) then if (npc:id() == task_info[task_id].task_giver_id) then size_t = size_t + 1 finished_tasks[id][size_t] = task_id end end else size_t = size_t + 1 finished_tasks[id][size_t] = task_id end end end count = count + 1 task_id = sec..tostring(count) end --]] end function trigger_fetch_func(task_id) --printf("triiger_fetch_func %s",task_id) local fetch_func = CFG_CACHE[task_id].fetch_func and xr_logic.parse_condlist(db.actor, "task_manager", "condlist", CFG_CACHE[task_id].fetch_func or "") if (fetch_func) then xr_logic.pick_section_from_condlist(db.actor,db.actor,fetch_func) end end function trigger_job_func(task_id) -- Tronex, fix for DRX --printf("triiger_fetch_func %s",task_id) local job_func = CFG_CACHE[task_id].on_job_descr and xr_logic.parse_condlist(db.actor, "task_manager", "condlist", CFG_CACHE[task_id].on_job_descr or "") if (job_func) then xr_logic.pick_section_from_condlist(db.actor,db.actor,job_func) end end function is_task_on_complete_stage(tsk) local tm = task_manager.get_task_manager() local task_info = tm.task_info if not (task_info[task_id]) then return false end return task_info[task_id].stage ~= nil and task_info[task_id].stage == (CFG_CACHE[task_id].stage_complete or 255) end function is_task_giver_valid(tsk) local id = tsk.task_giver_id local se_obj = id and alife_object(id) if not (se_obj) then --printf("is_task_giver_valid se_obj nil id=%s %s",id,tsk.id) return false end if (se_obj:clsid() == clsid.online_offline_group_s or se_obj:clsid() == clsid.script_trader) then return true end if not (IsStalker(nil,se_obj:clsid()) and se_obj:alive()) then printf("is_task_giver_valid giver not alive %s",tsk.id) return false end return true end